﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Serialization;
using S.EliminationOrDath.Infrastructure.Impl;
using S.EliminationOrDath.Infrastructure.Interface;
using Serilog.Events;
using Serilog;
using System.Text;
using Com.Ctrip.Framework.Apollo;
using Microsoft.EntityFrameworkCore;
using S.EliminationOrDath.Domain;
using Com.Ctrip.Framework.Apollo.Logging;
using Microsoft.OpenApi.Models;
using System.Reflection;
using S.EliminationOrDath.API.Extensions.AutoMapper;
using S.EliminationOrDath.Infrastructure;

namespace S.EliminationOrDath.Read.API.Extensions
{
    /// <summary>
    /// Program配置扩展
    /// </summary>
    public static class IOCServer
    {
        /// <summary>
        /// JWT授权验证
        /// </summary>
        /// <param name="builder"></param>
        public static void AddJWTServer(this WebApplicationBuilder builder)
        {
            #region 配置JWT授权验证

            builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(m =>
                {
                    //取出私钥
                    var secretByte = Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecretKey"]);
                    m.TokenValidationParameters = new TokenValidationParameters()
                    {
                        //验证发布者
                        ValidateIssuer = true,
                        ValidIssuer = builder.Configuration["Jwt:Issuer"],
                        //验证接收者
                        ValidateActor = true,
                        ValidAudience = builder.Configuration["Jwt:Audience"],
                        //验证是否过期
                        ValidateLifetime = true,
                        //验证私钥
                        IssuerSigningKey = new SymmetricSecurityKey(secretByte)
                    };
                });

            #endregion
        }

        /// <summary>
        /// 注入仓储
        /// </summary>
        /// <param name="builder"></param>
        public static void WarehousingAndService(this WebApplicationBuilder builder)
        {
            #region 仓储

            builder.Services.AddScoped<IEliminationRepository, EliminationRepository>();
            builder.Services.AddScoped<DBHelper>();

            builder.Services.AddScoped<ISheepDeathRepository, SheepDeathRepository>();
            #endregion
        }

        /// <summary>
        /// 配置JSON修补
        /// </summary>
        /// <param name="builder"></param>
        public static void JSONMending(this WebApplicationBuilder builder)
        {
            //JSON修补
            builder.Services.AddControllers().AddNewtonsoftJson(m =>
            {
                // 使用默认的合同解析器
                m.SerializerSettings.ContractResolver = new DefaultContractResolver();
                // 设置日期格式为 年月日时分秒
                m.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
            });
        }

        /// <summary>
        /// Serilog日志
        /// </summary>
        /// <param name="builder"></param>
        public static void AddSerilog(this WebApplicationBuilder builder)
        {
            Log.Logger = new LoggerConfiguration()
               .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) // 排除Microsoft的日志
               .Enrich.FromLogContext() // 注册日志上下文
               .WriteTo.Logger(configure => configure // 输出到文件
                   .MinimumLevel.Debug()
                   .WriteTo.File(
                       $"logs\\log.txt", // 单个日志文件，总日志，所有日志存到这里面
                       rollingInterval: RollingInterval.Day,
                       outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u20}] {Message:lj}{NewLine}"
                   )
               )
               .CreateLogger();
            builder.Host.UseSerilog();
        }

        /// <summary>
        /// 配置Apollo分布式配置中心
        /// </summary>
        public static void ApolloConfig(this WebApplicationBuilder builder)
        {
            builder.Host.ConfigureAppConfiguration((hostingContext, bur) => { LogManager.UseConsoleLogging(Com.Ctrip.Framework.Apollo.Logging.LogLevel.Trace); bur.AddApollo(bur.Build().GetSection("Apollo")).AddDefault(); });
        }

        /// <summary>
        /// 根据Apollo配置上下文
        /// </summary>
        /// <param name="builder"></param>
        public static void ApolloDbContext(this WebApplicationBuilder builder)
        {
            // 获取连接字符串，如果Apollo中没有找到，则使用默认值
            string defaultConnectionString = "server=10.31.56.5;uid=sa;pwd=1;database=SheepStorage";
            string connectionString = builder.Configuration.GetValue("ConnectionString", defaultConnectionString);

            // 注入上下文
            builder.Services.AddDbContext<EliminationDbContext>(m => m.UseSqlServer(connectionString));
        }

        /// <summary>
        /// Swagger配置
        /// </summary>
        /// <param name="builder"></param>
        public static void AddSwaggerOption(this WebApplicationBuilder builder)
        {
            #region swagger 配置

            //swagger添加报文头，方便做登录和退出：
            builder.Services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "EliminationOrDath", Version = "v1" });
                //配置注释显示swagge ui当中
                var xmlfile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlpath = Path.Combine(AppContext.BaseDirectory, xmlfile);
                c.IncludeXmlComments(xmlpath, true);
                //Token绑定到configureServices
                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
                    Type = SecuritySchemeType.ApiKey,
                    Description = "直接在下框中输入Bearer {token}（注意两者之间是一个空格）",
                    Name = "Authorization",//jwt默认的参数名称
                    BearerFormat = "JWT",
                    Scheme = "Bearer"
                });
                c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                  {
                    new OpenApiSecurityScheme
                    {
                      Reference=new OpenApiReference
                      {
                        Type=ReferenceType.SecurityScheme,
                        Id="Bearer"
                      }
                    },
                    new string[] {}
                  }
                });
            });

            #endregion swagger 配置
        }

        /// <summary>
        /// AutoMapper配置使用
        /// </summary>
        public static void AddAutoMappers(this WebApplicationBuilder builder)
        {
            builder.Services.AddAutoMapper(typeof(SetProfile));
        }
    }
}
